package li.kaeppe.travel.tracker.domain;

import java.util.List;

import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

import org.hibernate.annotations.IndexColumn;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.userdetails.UserDetails;

@Entity
@Table(name="TT_USER",
		uniqueConstraints = {@UniqueConstraint(columnNames={"username"})}
)
@javax.persistence.SequenceGenerator(name="SEQ_USER", sequenceName="USER_SEQUENCE")
public class User implements UserDetails {

	/* **************************************************** */
	/*                      CONSTANTS                       */
	/* **************************************************** */

	private static final long serialVersionUID = 5328429141964522829L;
	
	/* **************************************************** */
	/*                     MEMBER FIELDS                    */
	/* **************************************************** */

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO, generator="SEQ_USER")
	private long id;

	@Column(nullable=false, length=32)
	private String username;
	
	@Column(nullable=false, length=32)
	private String password;
	
	@Basic
	private boolean enabled = true;
	
	@Basic
	private boolean accountNonLocked = true;
	
	@Basic
	private boolean accountNonExpired = true;
	
	@ManyToMany(
			targetEntity=UserRole.class,
			cascade={CascadeType.PERSIST, CascadeType.MERGE}
			)
	@JoinTable(
			name="TT_USER_ROLE",
			joinColumns={@JoinColumn(name="USER_ID")},
			inverseJoinColumns={@JoinColumn(name="ROLE_ID")}
			)
	@IndexColumn(name = "INDX")
	private UserRole[] authorities;
	
	//@OneToMany(mappedBy="user", cascade= {CascadeType.ALL})
	@OneToMany(mappedBy="user", fetch = FetchType.EAGER, cascade= {CascadeType.ALL})
	private List<Trip> trips;
	
	/* **************************************************** */
	/*                      CONSTRUCTOR                     */
	/* **************************************************** */
	
	public User() {
		super();
	}
	
	public User(String username, String password) {
		this();
		this.setUsername(username);
		this.setPassword(password);
	}
	
	public User(User user) {
		this(user.getUsername(), user.getPassword());
		this.setId(user.getId());
		this.setAccountNonLocked(user.isAccountNonLocked());
		this.setEnabled(user.isEnabled());
	}
	
	/* **************************************************** */
	/*                    PUBLIC METHODS                    */
	/* **************************************************** */

	public boolean isAdministrator() {
		boolean admin = false;
		
		for(GrantedAuthority authority: authorities) {
			if(authority.equals("ROLE_ADMINISTRATOR")) {
				admin = true;
			}
		}
		
		return admin;
	}
	
	/* **************************************************** */
	/*                  PROTECTED METHODS                   */
	/* **************************************************** */

	/* **************************************************** */
	/*                   PRIVATE METHODS                    */
	/* **************************************************** */

	/* **************************************************** */
	/*                  GETTERS AND SETTERS                 */
	/* **************************************************** */

//	public GrantedAuthority[] getAuthorities() {
//		return new GrantedAuthority[] {
//			new GrantedAuthority () {
//
//				private static final long serialVersionUID = -445619394724764159L;
//
//				public String getAuthority() {
//					return "ROLE_USER";
//				}
//
//				public int compareTo(Object o) {
//					if(o instanceof GrantedAuthority) {
//						String auth = ((GrantedAuthority)o).getAuthority();
//						return auth.compareTo("ROLE_USER");
//					} else {
//						return -1;
//					}
//				}
//			}
//		};
//	}

	public void setPassword(String password) {
		this.password = password;
	}
	
	public String getPassword() {
		return password;
	}

	public void setUsername(String username) {
		this.username = username;
	}
	
	public String getUsername() {
		return username;
	}

	public void setAccountNonExpired(boolean accountNonExpired) {
		this.accountNonExpired = accountNonExpired;
	}
	
	public boolean isAccountNonExpired() {
		return accountNonExpired;
	}

	public void setAccountNonLocked(boolean accountNonLocked) {
		this.accountNonLocked = accountNonLocked;
	}
	
	public boolean isAccountNonLocked() {
		return accountNonLocked;
	}

	public boolean isCredentialsNonExpired() {
		return true;
	}

	public void setEnabled(boolean enabled) {
		this.enabled = enabled;
	}
	
	public boolean isEnabled() {
		return enabled;
	}

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public List<Trip> getTrips() {
		return trips;
	}

	public void setTrips(List<Trip> trips) {
		this.trips = trips;
	}

	public UserRole[] getAuthorities() {
		return authorities;
	}

	public void setAuthorities(UserRole[] authorities) {
		this.authorities = authorities;
	}
	
}
